﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace YYS.Controllers
{

    public abstract class ControlerEx : System.Web.Mvc.Controller
    {
        protected ControlerEx()
            : base() { }


        protected internal static System.Web.Mvc.JsonResult backJson(object obj)
        {
            var json = new System.Web.Mvc.JsonResult()
            {
                ContentType = ReqContentType.Json,
                ContentEncoding = System.Text.Encoding.UTF8,
                MaxJsonLength = int.MaxValue,
                Data = obj
            };
            return json;
        }

        protected internal static System.Web.Mvc.JsonResult backJson(int code, string errmsg, object data = null)
        {
            var json = new System.Web.Mvc.JsonResult()
            {
                ContentType = ReqContentType.Json,
                ContentEncoding = System.Text.Encoding.UTF8,
                MaxJsonLength = int.MaxValue
            };
            if (data != null) json.Data = new { code = code, errmsg = errmsg, data = data };
            else json.Data = new { code = code, errmsg = errmsg };

            return json;
        }
        #region 字节转换
        internal static string GetFileSize(long bytes)
        {
            const long kilobyte = 1024;
            const long megabyte = 1024 * kilobyte;
            const long gigabyte = 1024 * megabyte;

            if (bytes >= gigabyte)
                return $"{bytes / (double)gigabyte:F2} GB";

            if (bytes >= megabyte)
                return $"{bytes / (double)megabyte:F2} MB";

            return $"{bytes / (double)kilobyte:F2} KB";
        }
        #endregion
        #region 星期转换
        /// <summary>
        /// 星期转换
        /// </summary>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <param name="day"></param>
        /// <returns></returns>
        internal static string GetWeekDay(int year, int month, int day)
        {
            string str = "";
            var dt = new DateTime(year, month, day);
            string[] arr = { "日", "一", "二", "三", "四", "五", "六" };
            str = arr[(int)(dt.DayOfWeek)];
            return str;
        }

        internal static string GetWeekDay(DateTime dt)
        {
            string str = "";
            if (dt != null)
            {
                string[] arr = { "日", "一", "二", "三", "四", "五", "六" };
                str = "星期" + arr[(int)(dt.DayOfWeek)];
            }
            return str;
        }

        internal static string GetWeekDay(int week)
        {
            return "星期" + (week == 1 ? "一" : week == 2 ? "二" : week == 3 ? "三" : week == 4 ? "四" : week == 5 ? "五" : week == 6 ? "六" : week == 7 ? "七" : "？");
        }
        #endregion

        /// <summary>
        /// WebRequest Post
        /// </summary>
        /// <param name="Url">地址</param>
        /// <param name="Data">Post数据</param>
        /// <param name="ContentType">类型 xml：text/xml;charset=utf-8  json：application/json；  query：application/x-www-form-urlencoded</param>
        /// <param name="encoding">编码方式</param>
        /// <param name="Headers">自定义请求头</param>
        /// <param name="timeOut">超时时间，以秒为单位</param>
        /// <returns></returns>
        public static string HttpPostByWebRequest(string Url, string Data, string ContentType, System.Text.Encoding encoding, Dictionary<string, string> Headers = null, int timeOut = 100)
        {
            var aResult = string.Empty;

            HttpWebRequest httpWebRequest = null;
            WebResponse webResponse = null;
            try
            {
                byte[] postData = encoding.GetBytes(Data);
                GC.Collect();
                if (Url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, errors) => true);
                    httpWebRequest = (HttpWebRequest)WebRequest.Create(Url);
                    httpWebRequest.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    httpWebRequest = (HttpWebRequest)WebRequest.Create(Url);
                }
                httpWebRequest.ServicePoint.Expect100Continue = false;
                httpWebRequest.ServicePoint.UseNagleAlgorithm = false;
                httpWebRequest.ServicePoint.ConnectionLimit = 65500;
                httpWebRequest.AllowWriteStreamBuffering = false;
                httpWebRequest.Proxy = null;
                httpWebRequest.Timeout = timeOut * 1000;
                httpWebRequest.ReadWriteTimeout = timeOut * 1000;
                //httpWebRequest.KeepAlive = false;
                httpWebRequest.ProtocolVersion = HttpVersion.Version11;

                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = ContentType;
                httpWebRequest.ContentLength = postData.Length;
                if (Headers != null && Headers.Keys.Count > 0)
                {
                    foreach (var k in Headers)
                    {
                        httpWebRequest.Headers.Add(k.Key, k.Value);
                    }
                }
                using (System.IO.Stream stream = httpWebRequest.GetRequestStream())
                {
                    stream.Write(postData, 0, postData.Length);
                    stream.Flush();
                    stream.Close();
                }
                webResponse = httpWebRequest.GetResponse();
                using (Stream responseStream = webResponse.GetResponseStream())
                {
                    using (System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, encoding))
                    {
                        aResult = reader.ReadToEnd();
                    }
                    responseStream.Flush();
                    responseStream.Close();
                    responseStream.Dispose();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                try
                {
                    if (webResponse != null)
                    {
                        webResponse.Close();
                        webResponse = null;
                    }
                    if (httpWebRequest != null)
                    {
                        httpWebRequest.Abort();
                        httpWebRequest = null;
                    }
                    GC.Collect();
                }
                catch { }
            }
            return aResult;
        }
        /// <summary>
        ///  WebRequest Get
        /// </summary>
        /// <param name="Url">地址</param>
        /// <param name="encoding">编码</param>
        /// <param name="timeOut">超时时间，以秒为单位</param>
        /// <returns></returns>
        public static string HttpGetByWebRequest(string Url, System.Text.Encoding encoding, int timeOut = 100)
        {
            var aResult = string.Empty;

            HttpWebRequest httpWebRequest = null;
            WebResponse webResponse = null;
            try
            {
                GC.Collect();
                if (Url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, errors) => true);
                    httpWebRequest = (HttpWebRequest)WebRequest.Create(Url);
                    httpWebRequest.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    httpWebRequest = (HttpWebRequest)WebRequest.Create(Url);
                }
                httpWebRequest.ServicePoint.Expect100Continue = false;
                httpWebRequest.ServicePoint.UseNagleAlgorithm = false;
                httpWebRequest.ServicePoint.ConnectionLimit = 65500;
                httpWebRequest.AllowWriteStreamBuffering = false;
                httpWebRequest.Proxy = null;
                httpWebRequest.Timeout = timeOut * 1000;
                httpWebRequest.ReadWriteTimeout = timeOut * 1000;
                //httpWebRequest.KeepAlive = false;
                httpWebRequest.Method = "GET";
                webResponse = httpWebRequest.GetResponse();
                using (Stream responseStream = webResponse.GetResponseStream())
                {
                    using (System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, encoding))
                    {
                        aResult = reader.ReadToEnd();
                    }
                    responseStream.Flush();
                    responseStream.Close();
                    responseStream.Dispose();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                try
                {
                    if (webResponse != null)
                    {
                        webResponse.Close();
                        webResponse = null;
                    }
                    if (httpWebRequest != null)
                    {
                        httpWebRequest.Abort();
                        httpWebRequest = null;
                    }
                    GC.Collect();
                }
                catch { }
            }
            return aResult;
        }

        internal JsonResult _DBERROR(YYS.dbHelper db)
        {
            if (db.HasSystemError)
            {
                var log = new YYS.LogModel("YYSService", "Helper", "GETdbHelper", "数据库操作错误");
                log.Add("dbHelper", db.getDetail()).AddSystemError(db.Ex != null ? db.Ex.ToString() : db.Error);
                Helper.Log(log);
            }
            return backJson(1,!db.HasSystemError ? db.Error : "系统内部错误.DB");
        }

        #region Result
        [CompressHtml]
        [HttpGet]
        public virtual System.Web.Mvc.ActionResult Result()
        {
            int? AddClose = null;
            if (Request["AddClose"] != null && Request["AddClose"].xTrim() == "1") AddClose = 1;

            int? AutoTimeout = null;
            if (Request["AutoTimeout"] != null)
            {
                AutoTimeout = Request["AutoTimeout"].xTo<int>(0);
                if (AutoTimeout <= 0) AutoTimeout = null;
            }
            int? Top = null;
            if (Request["Top"] != null && Request["Top"].xTrim() == "0") Top = 0;

            var model = new YYS.ResultModel()
            {
                Title = Request["title"],
                Msg = Request["msg"],
                Top = Top,
                AddClose = AddClose,
                Icon = Request["Icon"].xTo<int>(0),
                AutoURL = Request["AutoURL"],
                AutoTimeout = AutoTimeout,
                OkButton = Request["OkButton"],
                OkLink = Request["OkLink"],
                CancelButton = Request["CancelButton"],
                CancelLink = Request["CancelLink"],
                FootText = Request["FootText"]
            };
            return View("~/Views/Shared/Result.cshtml", model);
        }

        public string getResultHtm(YYS.ResultModel model, string fileName = null)
        {
            string htmPath = null;
            try
            {
                var folder = Xcode.API.xHostPath("~/REST/");
                if (!System.IO.Directory.Exists(folder))
                {
                    System.IO.Directory.CreateDirectory(folder);
                }

                htmPath = "~/REST/" + (fileName == null ? Session.SessionID : fileName) + ".htm";
                var context = this.ControllerContext;
                var result = ViewEngines.Engines.FindView(context, "~/Views/Shared/Result.cshtml", "");
                context.Controller.ViewData.Model = model;

                if (result.View == null) return null;
                var filePath = Xcode.API.xHostPath(htmPath);
                using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(filePath, false, System.Text.Encoding.UTF8))
                {
                    ViewContext viewContext = new ViewContext(context, result.View, this.ViewData, this.TempData, streamWriter);
                    viewContext.View.Render(viewContext, streamWriter);
                    streamWriter.Flush();
                    streamWriter.Close();
                }
                if (Url == null)
                {
                    Url = new UrlHelper(Request.RequestContext);
                }
                return Url.Content(htmPath);

            }
            catch
            {
                return null;
            }
        }

        public string getResultUri(YYS.ResultModel model, string fileName = null)
        {
            return Url.Action("Result", model);
        }

        public virtual System.Web.Mvc.ActionResult ToResult(YYS.ResultModel model)
        {
            return RedirectToAction("Result", model);
        }
        #endregion

    }
}
namespace System
{
    using YYS;
    using System.Web.Mvc.Html;
    using YYS.Sys;

    /// <summary>
    /// 压缩HTML
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class CompressHtml : Attribute
    {
        public CompressHtml() { }
    }

    public static class LoginAuthorizeExtentions
    {
        public static T_S_OperatorInfo getLoginOptorInfo(this HttpRequestBase Request)
        {
            return Request.RequestContext.RouteData.DataTokens["__CurrentOperator"] as YYS.Sys.T_S_OperatorInfo;
        }

        #region
        public static string checkBrowser(this HttpRequestBase Request)
        {
            var browserType = Request.Browser.Type;
            if (browserType.xRange("IE6", "InternetExplorer6", "IE7", "InternetExplorer7", "IE8", "InternetExplorer8", "IE9", "InternetExplorer9", "IE10", "InternetExplorer10"))
            {
                return browserType;
            }
            return null;
        }
        #endregion

        #region

        static string Compress(string text)
        {
            var reg = new System.Text.RegularExpressions.Regex(@"\s*(</?[^\s/>]+[^>]*>)\s+(</?[^\s/>]+[^>]*>)\s*");
            text = reg.Replace(text, m => m.Groups[1].Value + m.Groups[2].Value);
            //移除html标签之间的空格 
            text = new System.Text.RegularExpressions.Regex(@"(?<=>)[\s|\n|\t]*(?=<)").Replace(text, string.Empty);
            //移除多余空格和换行符
            text = new System.Text.RegularExpressions.Regex(@"\n+\s+").Replace(text, string.Empty);
            return text;
        }

        public static string vueComponent(this System.Web.Mvc.WebViewPage page, string viewPath)
        {
            if (string.IsNullOrWhiteSpace(viewPath))
            {
                return new { code = 1, errmsg = "404.1 - 页面不存在" }.xConvertObjectToJson(false);
            }
            if (!System.IO.File.Exists(Xcode.API.xHostPath(viewPath)))
            {
                return new { code = 1, errmsg = "404.2 - 页面不存在" }.xConvertObjectToJson(false);
            }
            try
            {
                string text = page.Html.Partial(viewPath).ToString();

                string template = "", script = "", style = "";
                var g = new System.Text.RegularExpressions.Regex(@"<template[^>]*>([\s\S]*)<\/template>", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Match(text);
                if (g.Success)
                {
                    text = text.Replace(g.Value, "");
                    if (g.Groups.Count > 1) template = Compress(g.Groups[1].Value);
                }

                g = new System.Text.RegularExpressions.Regex(@"<script[^>]*>([\s\S]*?)<\/script>", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Match(text);
                if (g.Success && g.Groups.Count > 1) script = new Microsoft.Ajax.Utilities.Minifier().MinifyJavaScript(g.Groups[1].Value);

                g = new System.Text.RegularExpressions.Regex(@"<style[^>]*>([\s\S]*?)<\/style>", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Match(text);
                if (g.Success && g.Groups.Count > 1) style = new Microsoft.Ajax.Utilities.Minifier().MinifyStyleSheet(g.Groups[1].Value);

                template = template.Replace("<component is=\"style\" />", "<component is=\"style\" scoped type=\"text/css\">" + style + "</component>");

                return new { code = 0, errmsg = "", data = new { template = template.xToBase64(), script = script.xToBase64() } }.xConvertObjectToJson(false);
            }
            catch (Exception ex)
            {
                return new { code = 1, errmsg = ex.Message }.xConvertObjectToJson(false);
            }
        }
        #endregion
    }

    public sealed class LoginAuthorize : System.Web.Mvc.AuthorizeAttribute
    {
        public LoginAuthorize()
        {
            this.reqType = ReqFromType.Default;
        }
        /// <summary>
        /// 请求来源
        /// </summary>
        public ReqFromType reqType { get; set; }
        /// <summary>
        /// 学校必须
        /// </summary>
        public bool schoolMust { get; set; }
        /// <summary>
        /// 验证学校权限
        /// </summary>
        public bool schoolAccess { get; set; }
        /// <summary>
        /// 验证管理员权限ID
        /// </summary>
        public int funcId { get; set; }
        /// <summary>
        /// 验证教师权限ID
        /// </summary>
        public int teacherFuncId { get; set; }
        /// <summary>
        /// 用户必须
        /// </summary>
        public bool userMust { get; set; }
        /// <summary>
        /// 检查浏览器支持
        /// </summary>
        public bool checkBrowser { get; set; }
        /// <summary>
        /// 是否必须管理员
        /// </summary>
        public bool mustOptor { get; set; }

        short _needFunction = 1;
        /// <summary>
        /// 当操作人为操作员时有效 是否需要学校信息 0：不需要；1：需要校区ID 2：需要完整信息
        /// </summary>
        public short needFunction { get { return _needFunction; } set { _needFunction = value; } }

        short _needSchool = 1;
        /// <summary>
        /// 当操作人为操作员时有效 是否需要权限信息 0：不需要；1：需要权限ID 2：需要完整信息
        /// </summary>
        public short needSchool { get { return _needSchool; } set { _needSchool = value; } }

        bool _antiForgery = true;
        public bool antiForgery { get { return _antiForgery; } set { _antiForgery = value; } }

       
    }

    public sealed class MyLoginAuthorize
    {
        public MyLoginAuthorize(AuthorizationContext filterContext, ReqFromType _ReqType, bool _schoolMust, bool _schoolAccess, int _funcId, bool _userMust, bool _checkBrowser, bool _antiForgery, int _teacherFuncId, bool _mustOptor, short _needFunction, short _needSchool)
        {
            this.AuthorizationContext = filterContext;
            this.ReqType = _ReqType;
            this.schoolAccess = _schoolAccess;
            this.schoolMust = _schoolMust;
            this.funcId = _funcId;
            this.userMust = _userMust;
            this.checkBrowser = _checkBrowser;
            this.antiForgery = _antiForgery;
            this.teacherFuncId = _teacherFuncId;
            this.mustOptor = _mustOptor;
            this.needFunction = _needFunction;
            this.needSchool = _needSchool;
            this.IsPost = Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase);
        }


        public AuthorizationContext AuthorizationContext { get; private set; }
        public ReqFromType ReqType { get; private set; }
        public bool schoolMust { get; private set; }
        public bool schoolAccess { get; private set; }
        public int funcId { get; private set; }
        public int teacherFuncId { get; private set; }
        public bool userMust { get; private set; }
        public bool checkBrowser { get; private set; }
        public bool antiForgery { get; private set; }
        public bool mustOptor { get; private set; }
        public short needFunction { get; private set; }
        public short needSchool { get; private set; }

        public string Key { get; private set; }
        public bool IsPost { get; private set; }
        public HttpContextBase HttpContext { get { return AuthorizationContext.HttpContext; } }
        public HttpRequestBase Request { get { return HttpContext.Request; } }

        public void NotValid(string errmsg)
        {
            if (this.IsPost)
            {
                bool go = errmsg.Contains("超时") || errmsg.Contains("过期") || errmsg.Contains("员工已离职") || errmsg.Contains("用户不存在[101]") || errmsg.Contains("密码错误") || errmsg.Contains("非法请求");
                if (!go)
                {
                    this.AuthorizationContext.Result = new JsonResult() { Data = new { code = 999, errmsg = errmsg } };
                    return;
                }
            }

            var urlHelper = new UrlHelper(this.Request.RequestContext);

            var autoURL = this.ReqType == ReqFromType.Background ? urlHelper.Content("~/admin.aspx")
                : this.ReqType == ReqFromType.Default ? ""
                : this.ReqType == ReqFromType.Web ? urlHelper.Content("~/default.aspx")
                : this.ReqType == ReqFromType.WeiXin ? urlHelper.Content("~/weixin/go?state=userinfo")
                : this.ReqType == ReqFromType.WeixinQiye ? urlHelper.Content("~/weixin/qy?state=userinfo")
                : "";

            var model = new ResultModel() { IsPart = 0, Icon = 0, Title = "提示", Msg = errmsg, AutoTimeout = 3, AutoURL = autoURL };
            var controler = this.AuthorizationContext.Controller as YYS.Controllers.ControlerEx;
            string errUrl = controler != null ? controler.getResultUri(model, Xcode.API.xGuid()) : urlHelper.Action("Result", model);
            if (this.IsPost)
            {
                this.AuthorizationContext.Result = new JsonResult() { Data = new { code = -999, errmsg = errmsg, data = new { url = errUrl } } };
            }
            else
            {
                this.AuthorizationContext.Result = new System.Web.Mvc.RedirectResult(errUrl);
            }
        }

      
    }
}